home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 05.zip / BS1 part 5 / SASC_6.0_Disk_7.adf / Source_And_Examples / extras / Memlib / mwcontrol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-30  |  9.0 KB  |  374 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  2. * |_o_o|\\ Copyright (c) 1989 The Software Distillery.                    *
  3. * |. o.| ||          All Rights Reserved                                  *
  4. * | .  | ||          Written by Doug Walker                               *
  5. * | o  | ||          The Software Distillery                              *
  6. * |  . |//           235 Trillingham Lane                                 *
  7. * ======             Cary, NC 27513                                       *
  8. *                    BBS:(919)-471-6436                                   *
  9. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  10.  
  11. /* This file contains the routines that must be linked in to every pgm   */
  12. /* that wants to use MemLib - MWInit, MWTerm, MWCheck, MWHold, MWPurge   */
  13.  
  14. #include "mempriv.h"
  15.  
  16. struct MWGlobal mwg;
  17.  
  18. void _STIMWInit(void)
  19. {
  20.    MWInit(NULL, __MWFlags, __MWLogName);
  21. }
  22.  
  23. static void MWClose(void);
  24.  
  25. /* Initialization routine - should be called once before any memory */
  26. /* is allocated                                                     */
  27.  
  28. void MWInit(BPTR dbfh, LONG flags, char *dbnm)
  29. {
  30.  
  31.    /* Close any existing log that we opened */
  32.    if(mwg.flags & MWF_ACTIVE) MWClose();
  33.  
  34.    if(dbfh) mwg.dbfh = dbfh;
  35.    else if(dbnm) mwg.dbnm = dbnm;  /* Deferred logname */
  36.    else if(!(flags & MWF_NOLOG)) mwg.dbfh = Output();
  37.  
  38.    if(!(mwg.flags & MWF_ACTIVE))
  39.    {
  40.       mwg.lim[MWT_CHIP] = mwg.lim[MWT_FAST] = 0x7fffffff;
  41.  
  42.       mwg.task = FindTask(0L);
  43.    }
  44.  
  45.    mwg.flags = flags|MWF_ACTIVE;
  46. }
  47.  
  48. /* Termination routine */
  49.  
  50. void _STDMWTerm(void)
  51. {
  52.    int msgdone = 0;
  53.  
  54.    MWCheck();
  55.  
  56.    /* no need to trash the mem we may be about to free for good */
  57.    mwg.flags |= MWF_NOFTRASH;
  58.    mwg.flags &= ~MWF_CHECK;
  59.  
  60.    if(!(mwg.flags & MWF_NOFREE))
  61.    {
  62.       while(mwg.first)
  63.       {
  64.          if(!(mwg.first->myflags & MWF_ISMALLOC))
  65.          {
  66.             if(!msgdone)
  67.             {
  68.                MWPrintf("\7MemWatch ERROR: The following "
  69.                         "allocations were not freed:\n");
  70.                msgdone = 1;
  71.             }
  72.             MWPrintAlc(mwg.first);
  73.          }
  74.          MWFreeMem(mwg.first->memory, mwg.first->size, 0, "MWTERM", 0);
  75.       }
  76.    }
  77.  
  78.    MWPurge();  /* Really free all mem on the 'free' chain */
  79.  
  80.    MWClose();
  81.  
  82.    memset((char *)&mwg, 0, sizeof(struct MWGlobal));
  83.  
  84. }
  85.  
  86. /* For compatibility with previous versions */
  87. void MWTerm(void)
  88. {
  89.    _STDMWTerm();
  90. }
  91.  
  92. static void MWClose(void)
  93. {
  94.    char tmp[2];
  95.  
  96.    if(mwg.dbnm && mwg.dbfh)
  97.    {
  98.       MWPrintf("Hit RETURN to continue: ");
  99.       Read(mwg.dbfh, tmp, 1);
  100.       Close(mwg.dbfh);
  101.    }
  102.    mwg.dbfh = NULL;
  103. }
  104.  
  105. void MWLimit(LONG chiplim, LONG fastlim)
  106. {
  107.    mwg.lim[MWT_CHIP] = chiplim;
  108.    mwg.lim[MWT_FAST] = fastlim;
  109. }
  110.  
  111. int MWCheckA(struct MWAlc *mwa)
  112. {
  113.    int header, trailer;
  114.  
  115.    if(header=memcmp((char *)&mwa->header, MWHEADSTR, MW_HEADLEN))
  116.       MWPrintf("\7MemWatch ERROR: Header trashed\n");
  117.  
  118.    if(trailer=memcmp(mwa->memory+mwa->size, MWTRAILSTR, MW_TRAILLEN))
  119.       MWPrintf("\7MemWatch ERROR: Trailer trashed\n");
  120.  
  121.    if(header || trailer)
  122.    {
  123.       mwa->myflags |= MWF_REPORTED;
  124.       MWPrintAlc(mwa);
  125.       return(1);
  126.    }
  127.  
  128.    return(0);
  129. }
  130.  
  131. /* Validity check routine - checks all known allocations for overwrites */
  132. /* Called from every alloc and free routine, plus when specifically     */
  133. /* invoked                                                              */
  134.  
  135. void MWCheck(void)
  136. {
  137.    struct MWAlc *mwa;
  138.    char *tmpchar;
  139.    int error, tmpint;
  140.  
  141.    error = 0;
  142.    for(mwa=mwg.first; mwa; mwa=mwa->next)
  143.    {
  144.       if( (mwa->myflags & MWF_REPMASK) == MWF_REPORTED) continue;
  145.  
  146.       error = MWCheckA(mwa);
  147.    }
  148.  
  149.    for(mwa=mwg.freed; mwa; mwa=mwa->next)
  150.    {
  151.       if( (mwa->myflags & MWF_REPMASK) == MWF_REPORTED) continue;
  152.  
  153.       for(tmpint=0, tmpchar=mwa->memory; 
  154.           tmpint<mwa->size; 
  155.           tmpint++, tmpchar++)
  156.       {
  157.          if(*tmpchar != MWFTRASH)
  158.          {
  159.             mwa->myflags |= MWF_REPORTED;
  160.             error = 1;
  161.             MWPrintf("\7MemWatch ERROR: Freed memory modified\n");
  162.             MWPrintAlc(mwa);
  163.             break;
  164.          }
  165.       }
  166.    }
  167.  
  168.    if(error) MWHold();
  169. }
  170.  
  171. void MWHold(void)
  172. {
  173.    struct MWAlc *mwa;
  174.  
  175.    mwg.flags &= ~MWF_ERROR;
  176.  
  177.    /* We're attempting to go on, make all the sentinels correct */
  178.    for(mwa=mwg.first; mwa; mwa=mwa->next)
  179.    {
  180.       mwa->myflags &= ~MWF_REPMASK;
  181.       memcpy(mwa->header, MWHEADSTR, MW_HEADLEN);
  182.       memcpy((mwa->memory + mwa->size), MWTRAILSTR, MW_TRAILLEN);
  183.    }
  184.  
  185.    for(mwa=mwg.freed; mwa; mwa=mwa->next)
  186.    {
  187.       mwa->myflags &= ~MWF_REPMASK;
  188.       memset(mwa->memory, MWFTRASH, mwa->size);
  189.    }
  190. }
  191.  
  192. /* MWPurge really frees all memory placed on the 'freed' chain by */
  193. /* FreeMem() or free()                                            */
  194.  
  195. void MWPurge(void)
  196. {
  197.    struct MWAlc *cur, *next;
  198.  
  199.    for(cur=mwg.freed; cur; cur=next)
  200.    {
  201.       next = cur->next;
  202.       FreeMem(cur, cur->size + sizeof(struct MWAlc));
  203.    }
  204.    mwg.freed = NULL;
  205. }
  206.  
  207. void MWPrintf(char *ctl, ...)
  208. {
  209.    static char buffer[256];
  210.    va_list args;
  211.  
  212.    va_start(args, ctl);
  213.  
  214.    /* Note: The weird string constant is actually CODE that will */
  215.    /* be called by RawDoFmt.                                     */
  216.    RawDoFmt(ctl, args, (void (*))"\x16\xc0\x4e\x75", buffer);
  217.  
  218.    va_end(args);
  219.  
  220. /* If you don't have Commodore's debug.lib, KPutStr will come up undefined. */
  221. /* Edit mempriv.h and change the #define for USEDEBUGLIB to 0 in this case. */
  222. #if USEDEBUGLIB
  223.    if(mwg.flags & MWF_SERIAL) KPutStr(buffer);
  224.    else
  225. #endif
  226.    {
  227.       if(!mwg.dbfh && mwg.dbnm) mwg.dbfh = Open(mwg.dbnm, MODE_NEWFILE);
  228.       if(mwg.dbfh) Write(mwg.dbfh, buffer, strlen(buffer));
  229.    }
  230. }
  231.  
  232. void *MWAllocMem(long size, long flags, long ismalloc, char *file, long line)
  233. {
  234.    struct MWAlc *hd;
  235.    char *tmpchar;
  236.    int memtype;
  237.  
  238.    /* Force warning for malloc'd memory not freed if requested */
  239.    if(mwg.flags & MWF_MALLOCWRN) ismalloc = 0;
  240.  
  241.    if(!(mwg.flags & MWF_ACTIVE)) return(NULL);
  242.    if(mwg.flags & MWF_CHECK) MWCheck();
  243.  
  244.    if(size <= 0)
  245.    {
  246.       MWPrintf("\7Bad AllocMem length %ld from line %ld file \"%s\"\n",
  247.          size, line, file);
  248.       return(NULL);
  249.    }
  250.  
  251.    memtype = (flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
  252.    if(mwg.sum[memtype] + size > mwg.lim[memtype])
  253.    {
  254.       /* Over the limit, fail it */
  255.       MWPrintf("MemWatch: ");
  256.       if(memtype == MWT_CHIP)
  257.          MWPrintf("CHIP ");
  258.       else
  259.          MWPrintf("FAST ");
  260.       MWPrintf("memory allocation exceeds MWLimit amount\n");
  261.       return(NULL);
  262.    }
  263.  
  264.    while(!(tmpchar = (char *)AllocMem(sizeof(struct MWAlc)+size, flags)))
  265.    {
  266.       if(mwg.freed) MWPurge();
  267.       else return(NULL);
  268.    }
  269.    
  270.    hd = (struct MWAlc *)tmpchar;
  271.    hd->size = size;
  272.    hd->flags = flags;
  273.    hd->myflags = (ismalloc ? MWF_ISMALLOC : 0L);
  274.    hd->file = file;
  275.    hd->line = line;
  276.    memcpy(hd->header, MWHEADSTR, MW_HEADLEN);
  277.    memcpy(hd->memory+size, MWTRAILSTR, MW_TRAILLEN);
  278.  
  279.    if(!(flags & MEMF_CLEAR) && !(mwg.flags & MWF_NOATRASH))
  280.       memset(hd->memory, MWATRASH, size);   /* Trash the memory */
  281.  
  282.    hd->next = mwg.first;
  283.    mwg.first = hd;
  284.  
  285.    if((mwg.sum[memtype] += size) > mwg.max[memtype]) 
  286.       mwg.max[memtype] = mwg.sum[memtype];
  287.    ++(mwg.num[memtype]);
  288.  
  289.    return((char *)hd->memory);
  290. }
  291.  
  292. void MWFreeMem(void *mem, long size, long internal, 
  293.                char *file, long line)
  294. {
  295.    struct MWAlc *mwa, *prev;
  296.    int memtype;
  297.    int error = 0;
  298.  
  299.    if(!(mwg.flags & MWF_ACTIVE)) return;
  300.    if(mwg.flags & MWF_CHECK) MWCheck();
  301.  
  302.    for(prev = NULL, mwa = mwg.first; 
  303.        mwa && mwa->memory != mem; 
  304.        prev = mwa, mwa = mwa->next);
  305.  
  306.    if(!mwa)
  307.    {
  308.       for(mwa=mwg.freed; mwa && mwa->memory != mem; mwa=mwa->next);
  309.       if(mwa)
  310.       {
  311.          MWPrintf("\7Memory freed twice\n");
  312.          MWPrintAlc(mwa);
  313.       }
  314.       MWPrintf("\7Invalid FreeMem call, addr 0x%08lx length %ld\n"\
  315.                   "                       line %ld file \"%s\"\n",
  316.             mem, size, line, file);
  317.       error = 1;
  318.    }
  319.    else if(!internal && mwa->size != size)
  320.    {
  321.       MWPrintf("\7Incorrect FreeMem length %ld line %ld file \"%s\"\n", 
  322.          size, line, file);
  323.       MWPrintAlc(mwa);
  324.       error = 2;
  325.    }
  326.    else if(MWCheckA(mwa))
  327.      error = 2;
  328.  
  329.    if(error)
  330.    {
  331.       MWHold();
  332.       if(error == 1) return;
  333.    }
  334.  
  335.    memtype = (mwa->flags & MEMF_CHIP ? MWT_CHIP : MWT_FAST);
  336.    mwg.sum[memtype] -= mwa->size;
  337.    --mwg.num[memtype];
  338.  
  339.    if(prev) prev->next = mwa->next;
  340.    else     mwg.first = mwa->next;
  341.  
  342.    if(!(mwg.flags & MWF_NOFTRASH))
  343.       memset(mwa->memory, MWFTRASH, mwa->size);  /* Trash it */
  344.  
  345.    if(mwg.flags & MWF_NOFKEEP)
  346.      FreeMem((char *)mwa, mwa->size + sizeof(struct MWAlc));
  347.    else
  348.    {
  349.       mwa->next = mwg.freed;
  350.       mwg.freed = mwa;
  351.    }
  352. }
  353.  
  354. void *MWrealloc(void *mem, long size, char *file, long line)
  355. {
  356.    void *new;
  357.    struct MWAlc *mwa;
  358.  
  359.    if(!(new = MWAllocMem(size, 0, 1, file, line)))
  360.       return(NULL);
  361.  
  362.    for(mwa = mwg.first; 
  363.        mwa && mwa->memory != mem; 
  364.        mwa = mwa->next);
  365.  
  366.    if(mwa && mwa->size < size) size = mwa->size;
  367.  
  368.    memcpy(new, mem, size);
  369.  
  370.    MWFreeMem(mem, 0, 1, file, line);
  371.  
  372.    return(new);
  373. }
  374.